#include <LedControl.h>
#include <MsTimer2.h>

// LED矩阵
// DIN:8, CS:9, CLK:10
LedControl lc=LedControl(8,10,9,1);
// 游戏按键
const int BTN = 7;

int isGameStart = 0;
int isGameOver = 1;

int level = 5;

// 总分
int score = 0;
// 棋盘
byte checkerboard[8][8]={{0}};
// 停止结束标记
const int STOP = 0;
const int UP = 1;
const int DOWN = 2;
const int LEFT = 3;
const int RIGHT = 4;
// 蛇每个点的横纵坐标
int snakeRowList[100] = {0};   // 蛇的横坐标集合
int snakeColList[100] = {0};   // 蛇的纵坐标集合
// 蛇的方向
int direction = 0;
// 蛇尾下标位置
int snakeTailIndex = 0;
int foodRow = 0;
int foodCol = 0;
// 走过的蛇尾
int tmpRow = 0;
int tmpCol = 0;

byte smileFace[]={0x3c,0x42,0xa5,0x81,0xa5,0x99,0x42,0x3c};
byte jiongFace[]={0xff,0xa5,0xa5,0xc3,0xbd,0xa5,0xa5,0xff};
/**
 * 0,0点位于LED矩阵的左下角
 */

void msTimer2_func() {
  if(isGameStart && !isGameOver){
    changeSnake();
    checkGameOver();
    if(isGameOver){
      return;
    }
    if(foodIsExist()){
      randomFood();
      snakeTailIndex++;
      snakeRowList[snakeTailIndex] = tmpRow;
      snakeColList[snakeTailIndex] = tmpCol;
      score+=10;
    }
    refreshScreen();
  }
}

void setup(){
  // 硬件初始化
  pinMode(BTN, INPUT_PULLUP);
  Serial.begin(9600);
  lc.shutdown(0,false);
  lc.setIntensity(0,10);
  lc.clearDisplay(0);
}

void toStartGame(){
  direction = RIGHT;    // 初始方向
  // 初始化蛇的位置
  snakeRowList[0] = 3;
  snakeRowList[1] = 3;
  snakeRowList[2] = 3;
  snakeColList[0] = 4;
  snakeColList[1] = 3;
  snakeColList[2] = 2;
  snakeTailIndex = 2;
  // 食物初始化
  randomSeed(analogRead(A3));
  randomFood();
  int delayTime = (10 - level) * 100;
  MsTimer2::set(delayTime, msTimer2_func);
  MsTimer2::start();
  isGameStart = 1;
  isGameOver = 0;
  score = 0;
}

void toGameOver(){
  Serial.print("score:");
  Serial.println(score);
  MsTimer2::stop();
  isGameStart = 0;
}

/**
 * 杜邦线朝下
 */
void checkDirection(){
  int yVal = analogRead(A5);
  int xVal = analogRead(A4);
  if(yVal > 1000){
    delay(100);
    if(yVal > 1000){
      if(direction != LEFT){
        direction = RIGHT;
        return;
      }
    }
  }
  if(yVal < 50){
    delay(100);
    if(yVal < 50){
      if(direction != RIGHT){
        direction = LEFT;
        return;
      }
    }
  }
  if(xVal > 1000){
    delay(100);
    if(xVal > 1000){
      if(direction != UP){
        direction = DOWN;
        return;
      }
    }
  }
  if(xVal < 50){
    delay(100);
    if(xVal < 50){
      if(direction != DOWN){
        direction = UP;
        return;
      }
    }
  }
}

/**
 * 随机产生食物
 */
void randomFood(){
  for(;;){
    Serial.println("randomFood");
    foodRow = random(0, 7);
    foodCol = random(0, 7);
    if(!foodIsExist()){
      break;
    }
  }
}

// 判断蛇是否与食物重复
boolean foodIsExist(){
  for(int i = 0; i <= snakeTailIndex; i++){
    if(snakeRowList[i] == foodRow && snakeColList[i] == foodCol){
      return true;
    }
  }
  return false;
}

void showFace(byte *face){
  for(int i = 0; i < 8; i++){
    lc.setRow(0, i, face[i]);
  }
}
void showStartView(){
  showFace(smileFace);
  delay(200);
}
void showGameOverView(){
  delay(1000);
  showFace(jiongFace);
}
void loop(){
  if(!isGameStart && isGameOver){  // 等待游戏开始按键
    // 显示开始界面
    showStartView();
    // 等候按键
    for(;;){
//      Serial.println(digitalRead(BTN));
      if(0 == digitalRead(BTN)){
        toStartGame();
        break;
      }
    }
    Serial.println("wait game start...");
  }else if(isGameStart && !isGameOver){  // 游戏正在进行中
    checkDirection();
    delay(100);
  }else if(isGameStart && isGameOver){   // 游戏结束
    Serial.println("game is over...");
    // 显示结束界面
    showGameOverView();
    // 显示分数
    while(1){
      if(0 == digitalRead(BTN)){
        break;
      }
    }
    toGameOver();
  }
}

/**
 * 刷新屏幕
 */
void refreshScreen(){
  lc.clearDisplay(0);
  for(int i = 0; i <= snakeTailIndex; i++){
    lc.setLed(0, snakeRowList[i], snakeColList[i], 1);
  }
  lc.setLed(0, foodRow, foodCol, 1);
}

/**
 * 根据方向修改数组
 */
void changeSnake(){
  tmpRow = snakeRowList[snakeTailIndex];
  tmpCol = snakeColList[snakeTailIndex];
  // 修改蛇尾
  for(int i = snakeTailIndex; i>0; i--){
    snakeRowList[i] = snakeRowList[i-1];
    snakeColList[i] = snakeColList[i-1];
  }
  switch(direction){
    case UP:
      snakeRowList[0] = snakeRowList[1] + 1;
      snakeColList[0] = snakeColList[1];
      break;
    case DOWN:
      snakeRowList[0] = snakeRowList[1] - 1;
      snakeColList[0] = snakeColList[1];
      break;
    case LEFT:
      snakeRowList[0] = snakeRowList[1];
      snakeColList[0] = snakeColList[1] - 1;
      break;
    case RIGHT:
      snakeRowList[0] = snakeRowList[1];
      snakeColList[0] = snakeColList[1] + 1;
      break;
  }
  if(snakeRowList[0] >= 8){
    snakeRowList[0] = 0;
  }else if(snakeRowList[0] < 0){
    snakeRowList[0] = 7;
  }
  if(snakeColList[0] >= 8){
    snakeColList[0] = 0;
  }else if(snakeColList[0] < 0){
    snakeColList[0] = 7;
  }
}

/**
 * 检测游戏结束
 */
void checkGameOver(){
  for(int i = 0; i < snakeTailIndex; i++){
    for(int j = i + 1; j <= snakeTailIndex; j++){
      if(snakeColList[i] == snakeColList[j] && snakeRowList[i] == snakeRowList[j]){
        isGameOver = 1;
      }
    }
  }
}

